#include <err.h>
#include <libgen.h>
#include <stdio.h>
#include <string.h>

#define METARGS_POSIXLY_CORRECT
#include "../metaargs.h"
#include "../metaargs_helper.h"

/* clang-format off */
metaargs(basename, /* NOLINT */
	ma_long_short(ma_l_none(ma_l_id(multiple)), ma_s_none(a)),
	ma_long_short(ma_l_req(ma_l_id(suffix)), ma_s_req(s)),
	ma_long_short(ma_l_none(ma_l_id(zero)), ma_s_none(z)),
	METAARGS_END_DECL
);
/* clang-format on */

#define NFORMAT 6
const char *usage_str =
    "Usage: %s NAME [SUFFIX]\n"
    "   or: %s OPTION... NAME...\n"
    "Print NAME with any leading directory components removed.\n"
    "If specified, also remove a trailing SUFFIX.\n"
    "\n"
    "Mandatory arguments to long options are mandatory for short options "
    "too.\n"
    "  -a, --multiple       support multiple arguments and treat each as a "
    "NAME\n"
    "  -s, --suffix=SUFFIX  remove a trailing SUFFIX; implies -a\n"
    "  -z, --zero           end each output line with NUL, not newline\n"
    "      --help           display this help and exit\n"
    "      --version        output version information and exit\n"
    "\n"
    "Examples:\n"
    "  %s /usr/bin/sort          -> 'sort'\n"
    "  %s include/stdio.h .h     -> 'stdio'\n"
    "  %s -s .h include/stdio.h  -> 'stdio'\n"
    "  %s -a any/str1 any/str2   -> 'str1' followed by 'str2'";

static inline void  remove_suffix(char *name, const char *suffix);
static inline char *do_basename(char *path, const char *suffix);

int
main(int argc, char *argv[])
{
	METAARGS_PARSE(basename, config, argc, argv);

	/* -s implies -a */
	config.arg_multiple.is_set = config.arg_suffix.is_set;

	if (config.argc <= 0) errx(!0, "missing operand");

	if (config.arg_multiple.is_set)
		for (int i = 0; i < config.argc; i++)
			printf(
			    "%s%c",
			    do_basename(config.argv[i], config.arg_suffix.arg),
			    '\n' * !config.arg_zero.is_set);
	else
		printf("%s%c",
		       do_basename(config.argv[0],
				   config.argc == 2 ? config.argv[1] : NULL),
		       '\n' * !config.arg_zero.is_set);

	return 0;
}

static inline void
remove_suffix(char *name, const char *suffix)
{
	/* end of name and suffix */
	char	   *name_end = name + strlen(name);
	const char *suff_end = suffix + strlen(suffix);

	/* unless `name` is not entirely `suffix` */
	while (name_end > name && suff_end > suffix)
		if (*--name_end != *--suff_end) return;

	if (name_end > name) *name_end = '\0';
}

static inline char *
do_basename(char *path, const char *suffix)
{
	char *name;

	name = basename(path);

	if (suffix) remove_suffix(name, suffix);

	return name;
}
